#define F_CPU 1000000
#include <util/delay.h>
#define USARTBAUDRATE 12500
#define BAUDPRESCALE (1000000/(16UL*USARTBAUDRATE))- 1 //figure out the calculation
#include <avr/io.h>

void usart_init(void)
{
	UBRR0H = (unsigned char)((BAUDPRESCALE)>>8);
	UBRR0L = (unsigned char)BAUDPRESCALE;				//baud rate, calculated from value of UBRR0L
	UCSR0B	= (1<<TXEN0)|(1<<RXEN0);					//set up transmit and receive
	UCSR0C	= (1<<UCSZ00)|(1<<UCSZ01);					//Usart 8-bit char size, async mode UMSEL00 = 0

}
void usart_send(uint8_t data)
{
	while(!(UCSR0A&(1<<UDRE0)));						//do nothing until UDR is ready for data to be written to it
	UDR0 = data;										//DATA REG
}

void initADC(void)
{
	ADCSRA |= ((1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0));    //Prescaler at 128 so we have an 125Khz clock source
	ADMUX |= (1<<REFS0);
	ADMUX &= ~(1<<REFS1);						     //Avcc(+5v) as voltage reference
	ADMUX |= (1<<ADLAR);							//data will be left justified with reference voltage same as VCC
	ADCSRA |= (1<<ADEN);				            //Power up the ADC

}

void initPorts(void)
{
	DDRD |= (1<<PD0)|(1<<PD1);		//setup the UARt
	//no need to setup adc PC0(ADC0) is already 0
	DDRB = 0xFF;					//set portb as output
	DDRC |= 0b00011110;				//initiallize ports to be used for bcd
}

uint16_t readADC3(void)
{
	//PC0(ADC0) should be 0(INPUT)
	ADCSRA |= (1<<ADSC);			//start conversion
	while((ADCSRA&(1<<ADIF))==0);	//wait for end of conversion
	return ADC;
}

void flashNum(int outputNum, uint16_t val)
{
	switch(val){
		case 0: PORTB = 0b00111111;     break;
		case 1: PORTB = 0b00000110;     break;
		case 2: PORTB = 0b01011011;     break;
		case 3: PORTB = 0b01001111;     break;
		case 4: PORTB = 0b01100110;     break;
		case 5: PORTB = 0b01101101;     break;
		case 6: PORTB = 0b01111101;     break;
		case 7: PORTB = 0b00000111;     break;
		case 8: PORTB = 0b01111111;     break;
		case 9: PORTB = 0b01100111;     break;
	}
	PORTC &= 0b11100001;//reset port
	switch (outputNum)
	{
		case 0: PORTC |= 0b00000010;     break;
		case 1: PORTC |= 0b00000100;     break;
		case 2: PORTC |= 0b00001000;     break;
		case 3: PORTC |= 0b00010000;     break;
	}
}

int main(void)
{
	initPorts();
	usart_init();
	initADC();
	while(1)
	{
		uint16_t temp = readADC3()*5;
		uint16_t Dig1 = temp%10;
		uint16_t Dig2 = temp%100;
		uint16_t Dig3 = temp%1000;
		uint16_t Dig4 = temp%10000;
		for(int i=0; i<10000; i++)//1 sec refresh rate
		{
			flashNum(Dig1, 0);
			flashNum(Dig2, 1);
			flashNum(Dig3, 2);
			flashNum(Dig4, 3);
		}
		usart_send(Dig1);			//send lower order byte, BCD Format
		usart_send(Dig2);			//send lower order byte, BCD Format
		usart_send(Dig3);			//send lower order byte, BCD Format
		usart_send(Dig4);			//send lower order byte, BCD Format
		usart_send('\n');			//send newline
	}
	return 0;
}